<script setup lang="tsx">
import { computed, ref, watch } from 'vue';

import { useVbenModal } from '@vben/common-ui';
import { addFullName, listToTree } from '@vben/utils';

import {
  Alert,
  Button,
  Card,
  Checkbox,
  Form,
  Input,
  List,
  Modal,
  Progress,
  Select,
  Space,
  Spin,
  Typography,
} from 'ant-design-vue';

import { getCategoryListWithCount } from '#/api/interview/category';
import { getQuestionList, getQuestionsByAi } from '#/api/interview/question';

const emit = defineEmits<{ reload: [] }>();
const FormItem = Form.Item;
const CheckboxGroup = Checkbox.Group;
const { Text, Title } = Typography;

const form = ref({
  categoryId: undefined,
  prompt: '',
});

const [AiQuestionModal, modalApi] = useVbenModal({
  confirmText: '添加选中面试题',
  cancelText: '关闭',
  onOpenChange: (isOpen: boolean) => {
    if (isOpen) {
      resetForm();
      fetchCategories();
    }
  },
  onConfirm: handleSubmit,
});

const treeData = ref<any[]>([]);
const aiSuggestions = ref<any[]>([]);
const selectedSuggestions = ref<any[]>([]);
const existingQuestions = ref<any[]>([]);
const loading = ref(false);
const aiLoading = ref(false);
const formRef = ref();

// SSE相关状态
const sseProcessing = ref(false);
const sseMessage = ref('');
const sseResults = ref<any[]>([]);
// 每道题的进度状态
const questionProgressList = ref<
  { message: string; progress: number; question: string }[]
>([]);
// 每道题的模拟进度定时器
const progressIntervals = ref<number[]>([]);
// 当前正在处理的题目索引
const currentProcessingIndex = ref<number>(0);

// 全选相关
const selectAll = ref(false);
const indeterminate = ref(false);

// 获取所有分类的扁平化列表，用于查找分类名称
const flatCategoryList = computed(() => {
  const result: any[] = [];

  function flattenCategories(categories: any[], prefix = '') {
    categories.forEach((category) => {
      // 使用原始的categoryName，不带面试题数量
      const categoryName = category.categoryName.replace(/ \(\d+\)$/, '');
      const fullName = prefix ? `${prefix} / ${categoryName}` : categoryName;

      result.push({
        categoryId: category.categoryId,
        categoryName,
        fullName,
      });

      if (category.children && category.children.length > 0) {
        flattenCategories(category.children, fullName);
      }
    });
  }

  if (treeData.value && treeData.value.length > 0) {
    treeData.value.forEach((item) => {
      // 使用原始的categoryName，不带面试题数量
      const categoryName = item.categoryName.replace(/ \(\d+\)$/, '');
      if (item.children && item.children.length > 0) {
        flattenCategories(item.children, categoryName);
      }
    });
  }

  return result;
});

// 获取分类选项
async function fetchCategories() {
  try {
    const res = await getCategoryListWithCount({ status: '0' });
    const tree = listToTree(res.rows, {
      id: 'categoryId',
      pid: 'parentId',
      children: 'children',
    });
    addFullName(tree, 'categoryName', ' / ');

    // 处理分类名称，加上面试题数量
    const processNode = (node: any) => {
      const newNode = { ...node };
      // 当 interviewCount 为 null 时转换为 0
      const interviewCount =
        node.interviewCount !== undefined && node.interviewCount !== null
          ? node.interviewCount
          : 0;
      // 为面试题数量为0的分类添加特殊标记
      newNode.categoryName =
        interviewCount === 0
          ? `${node.categoryName} (${interviewCount})`
          : `${node.categoryName} (${interviewCount})`;
      // 保存原始的面试题数量，用于界面渲染时判断是否为0
      newNode.interviewCount = interviewCount;
      if (node.children) {
        newNode.children = node.children.map((child: any) =>
          processNode(child),
        );
      }
      return newNode;
    };

    treeData.value = tree.map((item) => processNode(item));
  } catch (error) {
    console.error('获取分类列表失败:', error);
  }
}

// 获取指定分类下的已有面试题
async function fetchExistingQuestions(categoryId: number) {
  try {
    const res = await getQuestionList({ categoryId });
    existingQuestions.value = res.rows || [];
  } catch (error) {
    console.error('获取已有面试题失败:', error);
    existingQuestions.value = [];
  }
}

// 监听分类的变化
watch(
  () => form.value.categoryId,
  async (newCategoryId) => {
    // 清空AI建议面试题
    aiSuggestions.value = [];
    selectedSuggestions.value = [];

    // 自动填充提示词
    if (newCategoryId !== undefined && newCategoryId !== null) {
      const category = flatCategoryList.value.find(
        (item: any) => item.categoryId === newCategoryId,
      );

      if (category) {
        // 设置固定的提示词并拼接分类全路径名称
        form.value.prompt = `这是关于"${category.fullName}"的面试题，请生成相关面试题，确保题目与该分类直接相关`;

        // 获取该分类下的已有面试题
        await fetchExistingQuestions(newCategoryId);
      } else {
        form.value.prompt = '';
        existingQuestions.value = [];
      }
    } else {
      form.value.prompt = '';
      existingQuestions.value = [];
    }
  },
);

// 监听选中项的变化，更新全选状态
watch(
  selectedSuggestions,
  (newSelected) => {
    if (newSelected.length === 0) {
      selectAll.value = false;
      indeterminate.value = false;
    } else if (newSelected.length === aiSuggestions.value.length) {
      selectAll.value = true;
      indeterminate.value = false;
    } else {
      selectAll.value = false;
      indeterminate.value = true;
    }
  },
  { deep: true },
);

// 通过AI获取面试题建议
async function getQuestionsByAiFromApi() {
  if (!form.value.categoryId) {
    Modal.warning({
      title: '提示',
      content: '请选择所属分类',
    });
    return;
  }

  if (!form.value.prompt.trim()) {
    Modal.warning({
      title: '提示',
      content: '请输入提示词',
    });
    return;
  }

  try {
    aiLoading.value = true;
    // res直接就是字符串数组
    const res = await getQuestionsByAi({
      categoryId: form.value.categoryId,
      prompt: form.value.prompt,
    });

    if (res && res.length > 0) {
      // 处理字符串数组格式的数据
      aiSuggestions.value = res.map((question: string, index: number) => ({
        question,
        key: `${form.value.categoryId}-${index}`,
      }));
      selectedSuggestions.value = [];
    } else {
      aiSuggestions.value = [];
      selectedSuggestions.value = [];
      Modal.info({
        title: '提示',
        content: '暂无相关面试题建议',
      });
    }

    // 重置全选状态
    selectAll.value = false;
    indeterminate.value = false;
  } catch (error) {
    console.error('获取AI面试题建议失败:', error);
    Modal.error({
      title: '错误',
      content: '获取AI面试题建议失败',
    });
  } finally {
    aiLoading.value = false;
  }
}

// 全选/取消全选
const handleSelectAllChange = (checked: boolean) => {
  if (checked) {
    // 全选
    selectedSuggestions.value = [...aiSuggestions.value];
  } else {
    // 取消全选
    selectedSuggestions.value = [];
  }
  selectAll.value = checked;
  indeterminate.value = false;
};

// 启动模拟进度（按顺序处理）
function startSequentialProgressSimulation() {
  // 重置当前处理索引
  currentProcessingIndex.value = 0;

  // 初始化第一道题的进度
  if (questionProgressList.value.length > 0) {
    startProgressSimulation(0);
  }
}

// 启动单个题目模拟进度
function startProgressSimulation(questionIndex: number) {
  // 清除可能存在的旧定时器
  if (progressIntervals.value[questionIndex]) {
    clearInterval(progressIntervals.value[questionIndex]);
  }

  // 初始化进度
  let progress = 0;

  // 设置新的进度模拟定时器
  // 每100ms更新一次进度，目标95%进度，用时约30秒
  // 30秒 = 30000毫秒，每次更新间隔100毫秒，共300次更新
  // 95%进度分300次更新，每次增加 95/300 ≈ 0.32%
  const increment = 9500 / 30_000; // 每毫秒增加的进度值

  progressIntervals.value[questionIndex] = window.setInterval(() => {
    // 使用缓动函数模拟从快到慢的进度增长
    // 这里使用平方根函数实现快到慢的效果
    const ratio = progress / 95;
    const easedProgress = 95 * Math.sqrt(ratio);

    const actualProgress = Math.min(95, Math.round(easedProgress));

    // 更新进度状态
    if (questionProgressList.value[questionIndex]) {
      questionProgressList.value[questionIndex].progress = actualProgress;
      questionProgressList.value[questionIndex].message =
        `正在处理中... (${actualProgress}%)`;
    }

    progress += increment;

    // 当进度达到95%时，清除定时器
    if (progress >= 95 && progressIntervals.value[questionIndex]) {
      clearInterval(progressIntervals.value[questionIndex]);
      progressIntervals.value[questionIndex] = 0;
    }
  }, 100); // 每100ms更新一次
}

// 处理下一道题
function processNextQuestion() {
  // 清除当前题目的模拟进度定时器
  if (progressIntervals.value[currentProcessingIndex.value]) {
    clearInterval(progressIntervals.value[currentProcessingIndex.value]);
    progressIntervals.value[currentProcessingIndex.value] = 0;
  }

  // 移动到下一题
  currentProcessingIndex.value++;

  // 如果还有下一题，则启动下一题的模拟进度
  if (currentProcessingIndex.value < questionProgressList.value.length) {
    // 更新下一题的状态为"等待处理..."
    questionProgressList.value[currentProcessingIndex.value].message =
      '等待处理...';
    startProgressSimulation(currentProcessingIndex.value);
  }
}

// 提交选中的面试题
async function handleSubmit() {
  if (selectedSuggestions.value.length === 0) {
    Modal.warning({
      title: '提示',
      content: '请至少选择一个面试题',
    });
    return;
  }

  try {
    loading.value = true;
    sseProcessing.value = true;
    sseMessage.value = '开始处理...';
    sseResults.value = [];

    // 初始化每道题的进度状态
    questionProgressList.value = selectedSuggestions.value.map(
      (item: any, index: number) => ({
        question: item.question,
        progress: 0, // 所有题目初始进度都为0
        message: '等待处理中...', // 所有题目初始状态都是等待处理
      }),
    );

    // 启动顺序模拟进度
    startSequentialProgressSimulation();

    // 构造查询参数
    const params = new URLSearchParams({
      categoryId: form.value.categoryId.toString(),
      questions: JSON.stringify(
        selectedSuggestions.value.map((item: any) => item.question),
      ),
    });

    // 创建EventSource连接
    // 修复部署到服务器后EventSource连接失败的问题
    const baseUrl = import.meta.env.VITE_GLOB_API_URL || '';
    const path = '/interview/question/completeQuestionsByAiSse';
    let url = '';

    if (baseUrl.startsWith('http')) {
      // 如果baseUrl是完整URL (如: http://117.72.199.127/prod-api)
      url = `${baseUrl}${path}?${params.toString()}`;
    } else if (baseUrl) {
        url = `${window.location.origin}${baseUrl}${path}?${params.toString()}`;
    } else {
      // 如果baseUrl为空，使用当前域名
      url = `${window.location.origin}${path}?${params.toString()}`;
    }

    const eventSource = new EventSource(url);

    eventSource.addEventListener('start', (event) => {
      sseMessage.value = event.data;
    });

    eventSource.addEventListener('progress', (event) => {
      const data = JSON.parse(event.data);
      sseResults.value.push(data);

      // 更新对应题目的进度
      if (data.index <= questionProgressList.value.length) {
        const questionIndex = data.index - 1; // data.index 从1开始，数组索引从0开始

        // 清除该题的模拟进度定时器
        if (progressIntervals.value[questionIndex]) {
          clearInterval(progressIntervals.value[questionIndex]);
          progressIntervals.value[questionIndex] = 0;
        }

        // 设置为完成状态
        questionProgressList.value[questionIndex].progress = 100;
        questionProgressList.value[questionIndex].message =
          data.status === 'success' ? `处理完成` : `处理失败: ${data.message}`;

        // 处理下一题的进度模拟
        processNextQuestion();
      }

      sseMessage.value =
        data.status === 'success'
          ? `第${data.index}题处理完成: ${data.content}`
          : `第${data.index}题处理失败: ${data.message}`;
    });

    eventSource.addEventListener('finish', (event) => {
      sseMessage.value = event.data;

      // 清除所有模拟进度定时器
      progressIntervals.value.forEach((intervalId) => {
        if (intervalId) {
          clearInterval(intervalId);
        }
      });
      progressIntervals.value = [];

      // 延迟关闭，确保状态更新完成
      setTimeout(() => {
        if (eventSource) {
          eventSource.close();
        }
        sseProcessing.value = false;
        Modal.success({
          title: '成功',
          content: `所有面试题处理完成，共处理 ${selectedSuggestions.value.length} 道题目`,
          onOk() {
            modalApi.close();
            emit('reload');
          },
        });
      }, 1000);
    });

    eventSource.addEventListener('error', (event) => {
      // 检查是否已经完成，避免在正常关闭时触发错误
      if (!sseProcessing.value) {
        return;
      }
      sseMessage.value = `处理出错: ${event.data || '连接异常'}`;
      sseProcessing.value = false;
      // 清除所有模拟进度定时器
      progressIntervals.value.forEach((intervalId) => {
        if (intervalId) {
          clearInterval(intervalId);
        }
      });
      progressIntervals.value = [];
      // 确保关闭连接
      if (eventSource) {
        eventSource.close();
      }
    });
  } catch (error) {
    console.error('完善面试题失败:', error);
    sseProcessing.value = false;
    // 清除所有模拟进度定时器
    progressIntervals.value.forEach((intervalId) => {
      if (intervalId) {
        clearInterval(intervalId);
      }
    });
    progressIntervals.value = [];
    Modal.error({
      title: '错误',
      content: '完善面试题失败',
    });
  } finally {
    loading.value = false;
  }
}

// 重置表单
function resetForm() {
  form.value = {
    categoryId: undefined,
    prompt: '',
  };
  aiSuggestions.value = [];
  selectedSuggestions.value = [];
  existingQuestions.value = [];

  // 重置SSE状态
  sseProcessing.value = false;
  sseMessage.value = '';
  sseResults.value = [];
  questionProgressList.value = [];

  // 清除所有模拟进度定时器
  progressIntervals.value.forEach((intervalId) => {
    if (intervalId) {
      clearInterval(intervalId);
    }
  });
  progressIntervals.value = [];

  // 重置当前处理索引
  currentProcessingIndex.value = 0;

  // 重置全选状态
  selectAll.value = false;
  indeterminate.value = false;
}

defineExpose({
  modalApi,
});
</script>

<template>
  <AiQuestionModal
    :destroy-on-close="true"
    title="AI生成面试题"
    wrap-class-name="ai-question-modal"
    class="h-[95vh] max-h-[95vh] w-[95%]"
    :centered="true"
    :confirm-loading="loading"
    :confirm-disabled="
      selectedSuggestions.length === 0 || sseProcessing || loading
    "
  >
    <Spin :spinning="loading || aiLoading">
      <Form ref="formRef" :model="form" layout="vertical">
        <div style="display: flex; gap: 20px; margin-bottom: 20px">
          <div style="flex: 1">
            <FormItem
              label="所属分类"
              name="categoryId"
              :rules="[{ required: true, message: '请选择所属分类' }]"
            >
              <Select
                v-model:value="form.categoryId"
                placeholder="请选择所属分类"
                show-search
                option-filter-prop="label"
                :disabled="sseProcessing"
              >
                <template v-for="item in treeData" :key="item.categoryId">
                  <Select.OptGroup
                    v-if="item.children && item.children.length > 0"
                    :label="item.categoryName"
                    :style="{ color: item.interviewCount === 0 ? 'red' : '' }"
                  >
                    <template
                      v-for="child in item.children"
                      :key="child.categoryId"
                    >
                      <Select.Option
                        v-if="!child.children || child.children.length === 0"
                        :value="child.categoryId"
                      >
                        <span
                          :style="{
                            color: child.interviewCount === 0 ? 'red' : '',
                          }"
                          >{{ child.categoryName }}</span
                        >
                      </Select.Option>
                      <template v-else>
                        <Select.Option
                          v-for="grandchild in child.children"
                          :key="grandchild.categoryId"
                          :value="grandchild.categoryId"
                        >
                          <span
                            :style="{
                              color:
                                grandchild.interviewCount === 0 ? 'red' : '',
                            }"
                            >{{ grandchild.categoryName }}</span
                          >
                        </Select.Option>
                      </template>
                    </template>
                  </Select.OptGroup>
                  <Select.Option v-else :value="item.categoryId">
                    <span
                      :style="{ color: item.interviewCount === 0 ? 'red' : '' }"
                      >{{ item.categoryName }}</span
                    >
                  </Select.Option>
                </template>
              </Select>
            </FormItem>
          </div>

          <div style="flex: 2">
            <FormItem
              label="提示词"
              name="prompt"
              :rules="[{ required: true, message: '请输入提示词' }]"
            >
              <Input
                v-model:value="form.prompt"
                placeholder="请输入提示词，如：Java相关的面试题"
                :disabled="sseProcessing"
              />
            </FormItem>
          </div>
        </div>

        <div style="display: flex; gap: 20px">
          <!-- 左侧区域 -->
          <div style="flex: 1">
            <FormItem>
              <Button
                type="primary"
                @click="getQuestionsByAiFromApi"
                :loading="aiLoading"
                :disabled="sseProcessing"
              >
                获取AI建议
              </Button>
            </FormItem>

            <!-- SSE处理进度显示 -->
            <div v-if="sseProcessing" style="margin-bottom: 20px">
              <div style="margin-bottom: 10px">
                <span>{{ sseMessage }}</span>
              </div>

              <!-- 每道题的独立进度条 -->
              <div
                v-for="(questionProgress, index) in questionProgressList"
                :key="index"
                style="
                  margin-bottom: 15px;
                  padding: 10px;
                  border: 1px solid #f0f0f0;
                  border-radius: 4px;
                "
              >
                <div style="margin-bottom: 5px; font-weight: 500">
                  第{{ index + 1 }}题: {{ questionProgress.question }}
                </div>
                <Progress
                  :percent="questionProgress.progress"
                  :status="
                    questionProgress.progress === 100 ? 'success' : 'active'
                  "
                />
                <div style="font-size: 12px; color: #666">
                  {{ questionProgress.message }}
                </div>
              </div>
            </div>

            <FormItem
              v-if="aiSuggestions.length > 0 && !sseProcessing"
              label="AI建议面试题"
            >
              <Alert
                message="以下是由AI根据提示词生成的相关面试题建议，请选择需要添加的面试题"
                type="info"
                show-icon
                style="margin-bottom: 12px"
              />
              <div
                style="
                  margin-bottom: 12px;
                  padding: 8px;
                  border: 1px solid #f0f0f0;
                  border-radius: 4px;
                "
              >
                <Checkbox
                  :checked="selectAll"
                  :indeterminate="indeterminate"
                  @change="(e: any) => handleSelectAllChange(e.target.checked)"
                  :disabled="sseProcessing"
                >
                  全选所有面试题
                </Checkbox>
                <span style="margin-left: 10px; color: #999; font-size: 12px">
                  (已选 {{ selectedSuggestions.length }} /
                  {{ aiSuggestions.length }})
                </span>
              </div>
              <div style="max-height: max-content; overflow-y: auto">
                <div
                  v-for="question in aiSuggestions"
                  :key="question.key"
                  style="
                    margin-bottom: 12px;
                    padding: 8px;
                    border: 1px solid #f0f0f0;
                    border-radius: 4px;
                  "
                >
                  <Checkbox
                    :value="question"
                    :checked="
                      selectedSuggestions.some((q) => q.key === question.key)
                    "
                    @change="(e: any) => {
                      if (e.target.checked) {
                        selectedSuggestions.push(question);
                      } else {
                        const index = selectedSuggestions.findIndex(q => q.key === question.key);
                        if (index > -1) {
                          selectedSuggestions.splice(index, 1);
                        }
                      }
                    }"
                    :disabled="sseProcessing"
                  >
                    <strong>{{ question.question }}</strong>
                  </Checkbox>
                </div>
              </div>
            </FormItem>
          </div>

          <!-- 右侧区域：显示已有面试题 -->
          <div style="flex: 1" v-if="form.categoryId">
            <Card title="已有面试题" size="small">
              <template #extra>
                <span style="font-size: 12px; color: #999">共 {{ existingQuestions.length }} 题</span>
              </template>
              <div style="max-height: 500px; overflow-y: auto">
                <List
                  v-if="existingQuestions.length > 0"
                  :data-source="existingQuestions"
                  size="small"
                  :pagination="{
                    pageSize: 10,
                    size: 'small',
                    hideOnSinglePage: true,
                  }"
                >
                  <template #renderItem="{ item }">
                    <List.Item>
                      <List.Item.Meta>
                        <template #title>
                          <Text ellipsis>{{ item.content }}</Text>
                        </template>
                      </List.Item.Meta>
                    </List.Item>
                  </template>
                </List>
                <div
                  v-else
                  style="text-align: center; padding: 20px; color: #999"
                >
                  该分类下暂无面试题
                </div>
              </div>
            </Card>
          </div>
        </div>
      </Form>

      <template #footer>
        <Space>
          <Button @click="modalApi.close()" :disabled="sseProcessing">
            取消
          </Button>
          <Button
            type="primary"
            @click="handleSubmit"
            :loading="loading"
            :disabled="
              selectedSuggestions.length === 0 || sseProcessing || loading
            "
          >
            添加选中面试题
          </Button>
        </Space>
      </template>
    </Spin>
  </AiQuestionModal>
</template>

<style scoped>
.ai-question-modal :deep(.ant-modal-content) {
  height: 70vh;
  overflow: hidden;
}

.ai-questionModal :deep(.ant-modal-body) {
  height: calc(70vh - 55px - 53px);
  overflow-y: auto;
}
</style>
